package com.sencorsta.ids.core.data.mysql;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sencorsta.ids.core.application.proxy.ProxyClient;
import com.sencorsta.ids.core.configure.GlobalConfigure;
import com.sencorsta.ids.core.configure.TypeProtocol;
import com.sencorsta.ids.core.configure.TypeSerialize;
import com.sencorsta.ids.core.entity.Server;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.core.tcp.socket.protocol.RpcMessage;
import io.netty.channel.Channel;

import java.util.concurrent.ConcurrentHashMap;

public abstract class DBService {

    protected String DATA_BASE_SERVER_NAME;

    public JSONArray select(String SQL, Object... parms) {
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("select", SQL, parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return json.getJSONObject("data").getJSONArray("list");
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return null;
    }

    public int insert(String SQL, Object... parms) {
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("insert", SQL, parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return json.getJSONObject("data").getIntValue("key");
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return -1;
    }

    public boolean update(String SQL, Object... parms) {
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("update", SQL, parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return true;
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return false;
    }

    public boolean delete(String SQL, Object... parms) {
        return update(SQL, parms);
    }

    public int add(String SQL, JSONObject parms) {
        parms.put("sql", SQL);
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("add", parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return json.getJSONObject("data").getIntValue("key");
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return -1;
    }

    public boolean delete(String SQL, JSONObject parms) {
        parms.put("sql", SQL);
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("delete", parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return true;
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return false;
    }

    public JSONObject get(String SQL, JSONObject parms) {
        parms.put("sql", SQL);
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("get", parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return json.getJSONObject("data");
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return null;
    }

    public JSONArray getList(String SQL, JSONObject parms) {
        return getList(SQL, parms, "");
    }

    public JSONArray getList(String SQL, JSONObject parms, String _SQL) {
        parms.put("sql", SQL);
        parms.put("_sql", _SQL);
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("getList", parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return json.getJSONObject("data").getJSONArray("list");
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return null;
    }

    public boolean mod(String SQL, JSONObject parms) {
        parms.put("sql", SQL);
        RpcMessage dbRes = ProxyClient.requestByType(sqlMessage("mod", parms), DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return true;
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return false;
    }

    public boolean executeMultiple(JSONArray list) {
        RpcMessage msg = new RpcMessage(TypeProtocol.TYPE_RPC_REQ);
        msg.method = "multipleExecute";
        msg.serializeType = TypeSerialize.TYPE_JSON;

        JSONObject sqlMsg = new JSONObject();
        sqlMsg.put("list", list);
        msg.data = JSON.toJSONString(sqlMsg).getBytes(GlobalConfigure.UTF_8);

        RpcMessage dbRes = ProxyClient.requestByType(msg, DATA_BASE_SERVER_NAME);
        JSONObject json = JSON.parseObject(new String(dbRes.data, GlobalConfigure.UTF_8));
        if (json.getIntValue("code") == 0) {
            return true;
        } else {
            Out.error(json.getIntValue("code"), " : ", json.getString("msg"));
        }
        return false;
    }

    public void executeMultipleAsyn(JSONArray list) {
        RpcMessage msg = new RpcMessage(TypeProtocol.TYPE_RPC_REQ);
        msg.method = "multipleExecute";
        msg.serializeType = TypeSerialize.TYPE_JSON;

        JSONObject sqlMsg = new JSONObject();
        sqlMsg.put("list", list);
        msg.data = JSON.toJSONString(sqlMsg).getBytes(GlobalConfigure.UTF_8);

        ProxyClient.sendByType(msg, DATA_BASE_SERVER_NAME);
    }



    //异步添加
    public void insertAsyn(String SQL, Object... parms) {
        RpcMessage msg=sqlMessage("insert", SQL, parms);
        msg.msgId=-1l;
        ProxyClient.sendByType(msg, DATA_BASE_SERVER_NAME);
    }

    //异步修改
    public void updateAsyn(String SQL, Object... parms) {
        RpcMessage msg=sqlMessage("update", SQL, parms);
        msg.msgId=-1l;
        ProxyClient.sendByType(msg, DATA_BASE_SERVER_NAME);
    }

    //异步修改
    public void updateAsynLock(String SQL, Object... parms) {
        RpcMessage msg=sqlMessage("updateLock", SQL, parms);
        msg.msgId=-1l;
        ProxyClient.sendByType(msg, DATA_BASE_SERVER_NAME);
    }


    //异步删除
    public void deleteAsyn(String SQL, Object... parms) {
        updateAsyn(SQL, parms);
    }


    private RpcMessage sqlMessage(String path, String SQL, Object[] parms) {
        RpcMessage selectMsg = new RpcMessage(TypeProtocol.TYPE_RPC_REQ);
        selectMsg.method = path;
        selectMsg.serializeType = TypeSerialize.TYPE_JSON;

        JSONObject sqlMsg = new JSONObject();
        sqlMsg.put("SQL", SQL);
        sqlMsg.put("args", JSON.toJSONString(parms));
        selectMsg.data = JSON.toJSONString(sqlMsg).getBytes(GlobalConfigure.UTF_8);
        return selectMsg;
    }



    private RpcMessage sqlMessage(String path, JSONObject parms) {
        RpcMessage selectMsg = new RpcMessage(TypeProtocol.TYPE_RPC_REQ);
        selectMsg.method = path;
        selectMsg.serializeType = TypeSerialize.TYPE_JSON;

        selectMsg.data = JSON.toJSONString(parms).getBytes(GlobalConfigure.UTF_8);
        return selectMsg;
    }

    public void waitUtilLoad(){
        while (ProxyClient.hasConnect(DATA_BASE_SERVER_NAME)==false){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
